﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RevClinic.Core.Commands;
using RevClinic.Core.Domain;
using NHibernate;
using NHibernate.Exceptions;
using RevClinic.Core.Services;
using FluentValidation;
using RevClinic.Core.Commands.Models;
using RevClinic.Core.Security;
using RevClinic.Core.Commands.ModelValidators;
using RevClinic.Core.Repositories;

namespace RevClinic.Core.Commands.Handlers
{
    public class UserCreateCommandHandler : CommandHandlerBase<UserCreateCommand, UserCreateModel>
    {
        private IUserService _userService;
        private IRoleRepository _roleRepository;
        private IEncrypter _encrypter;

        public UserCreateCommandHandler(
            ISessionFactory sessionFactory,
            IUserService userService,
            IRoleRepository roleRepository,
            IEncrypter encypter
            ) :
            base(sessionFactory)
        {
            _userService = userService;
            _roleRepository = roleRepository;
            _encrypter = encypter;
        }

        public override void HandleAction(UserCreateCommand cmd)
        {
            UserCreateModel model = cmd.Model;
            User user = null;
            switch (model.Type) {
                case UserType.Doctor:
                    user = CreateDoctorUser(model);
                    break;
                default:
                    user = CreateRegularUser(model);
                    break;
            }
            Session.Save(user);
        }

        public override IValidator<UserCreateModel> CreateModelValidator()
        {
            return new UserCreateModelValidator(_userService);
        }

        private User CreateRegularUser(UserCreateModel model)
        {
            return new User(
                new UserInfo(model.Login,
                    EncodePassword(model.Password),
                    model.FirstName,
                    model.Surname),
                _roleRepository.GroupFor(model.Type));
        }

        private Doctor CreateDoctorUser(UserCreateModel model)
        {
            return new Doctor(
                new UserInfo(model.Login,
                    EncodePassword(model.Password),
                    model.FirstName,
                    model.Surname),
                _roleRepository.GroupFor(model.Type));
        }

        private string EncodePassword(string plainPassword)
        {
            return _encrypter.Encode(plainPassword);
        }
    }
}
